#include "stdafx.h"
#include "CMath.h"

unsigned int CMath::srand_number = 0;


int CMath::RANDOM(int min, int max)
{
	int random_range = max - min + 1;
	
	return (min + (rand()%random_range));
}
//#ifndef MAC_OS
int CMath::MAXIMUM(int a, int b)
{
	return (a>b ? a : b);
}

int CMath::MINIMUM(int a, int b)
{
	return (a>b ? b : a);
}
//#endif

void CMath::PRE_RANDOM()
{
	srand(time(0) + srand_number);
}

int CMath::ABSOLUTE_VALUE(int x)
{
	return abs(x);
}

float CMath::ABSOLUTE_VALUE(float x)
{
	return abs(x);
}

float CMath::SQRT(float x)
{
	return sqrt(x);
}

float CMath::POW(float x, int y)
{
	return pow(x, y);
}

float CMath::SIN(float angle)
{
	return sin((float)(angle*PI/180));
}

float CMath::COS(float angle)
{
	return cos((float)(angle*PI/180));
}

float CMath::TAN(float angle)
{
	return tan((float)(angle*PI/180));
}

float CMath::ARCSIN(float sin)
{
	return (float)(asin(sin)*180.0/PI);
}

float CMath::ARCCOS(float cos)
{
	return (float)(acos(cos)*180.0/PI);
}

float CMath::ARCTAN(float tan)
{
	return (float)(atan(tan)*180.0/PI);
}

float CMath::DEG2RAD(float degrees)
{
	return (degrees*PI/180);
}

float CMath::RAD2DEG(float radians)
{
	return (radians*180/PI);
}

float CMath::DISTANCE(float x1, float y1, float x2, float y2)
{
	float dx = abs(x1 - x2);
	float dy = abs(y1 - y2);

	return SQRT(dx*dx + dy*dy);
}

void CMath::NORMALIZE(float &vx, float &vy)
{
	if (vx == 0 && vy ==0)
		return;
		
	float distance = SQRT(vx*vx + vy*vy);
	vx /= distance;
	vy /= distance;
}
//hao.ly add
bool CMath::CIRCLE_IN_RECT(float cX, float cY, float rad, float rX, float rY, float w, float h)
{
	float distance = 0;
	if(cX < rX) 
	{
		distance += CMath::POW(cX - rX, 2);
	}	
	else if (cX > rX + w)
	{
		distance += CMath::POW(cX - rX - w, 2);
	}

	if(cY < rY) 
	{
		distance += CMath::POW(cY - rY,2);
	}
	else if (cY > rY + h) 
	{
		distance += CMath::POW(cY - rY - h, 2);
	}
	
	if( distance <= CMath::POW(rad, 2))
	{
		return true; 
	}	
	else
	{
		return false;
	}	
}
float CMath::ANGLE(float xA, float yA, float xB, float yB)
{
	if (xB == xA)
	{
		if ((yB - yA) < 0)
			return  -90;
		else
			return 90;
			
	}
	
	double angle = ARCTAN( (yB-yA)/(xB-xA) );
	
	if ((xB - xA) < 0)
	{
		angle += 180;
	}
	
	if (angle > 180)
	{
		angle -= 360;
	}
	
	return angle;
}

float CMath::ANGLE(float vx, float vy)
{
	if (vx == 0)
	{
		if ((vy) < 0)
			return  -90;
		else
			return 90;
		
	}
	
	double angle = ARCTAN( vy/vx );
	
	if (vx < 0)
	{
		angle += 180;
	}
	
	if (angle > 180)
	{
		angle -= 360;
	}
	
	return angle;
}

float CMath::ANGLE_OF_2_VECTOR(float v1x, float v1y, float v2x, float v2y)
{
	float a1 = 0.0;
	
	if (v1x == 0)
	{
		a1 = 90.0;
	}
	else
	{
		a1 = ARCTAN(v1y/v1x);
	}

	if (a1 > 0)
	{
		if (v1y < 0)
		{
			a1 += 180;
		}
	}
	else
	{
		if (v1y > 0)
		{
			a1 += 180;
		}
		else
		{
			a1 += 360;
		}
	}
	
	float a2 = 0.0;
	
	if (v2x == 0)
	{
		a2 = 90.0;
	}
	else
	{
		a2 = ARCTAN(v2y/v2x);
	}
	
	if (a2 > 0)
	{
		if (v2y < 0)
		{
			a2 += 180;
		}
	}
	else
	{
		if (v2y > 0)
		{
			a2 += 180;
		}
		else
		{
			a2 += 360;
		}
	}
	
	return (a2-a1);
}

float CMath::DISTANCE(float vx, float vy)
{
	return SQRT(vx*vx + vy*vy);
}

void CMath::ROTATE_VECTOR(float &vx, float &vy, float angle)
{
	float dd = sqrt(vx*vx + vy*vy);
	
	float a = 0.0;
	
	if (vx == 0)
	{
		a = 90.0;
	}
	else
	{
		a = ARCTAN(vy/vx);
	}
	
	if (a > 0)
	{
		if (vy < 0)
		{
			a += 180;
		}
	}
	else
	{
		if (vy > 0)
		{
			a += 180;
		}
	}
	
	a += angle;
	
	vx = dd*COS(a);
	vy = dd*SIN(a);
}

// collision checking

bool CMath::LINE_ON_LINE(int xA1, int yA1, int xB1, int yB1, int xA2, int yA2, int xB2, int yB2)
{
    float s1_x, s1_y, s2_x, s2_y;
    s1_x = xB1 - xA1;     s1_y = yB1 - yA1;
    s2_x = xB2 - xA2;     s2_y = yB2 - yA2;

    float s, t;
    s = (-s1_y * (xA1 - xA2) + s1_x * (yA1 - yA2)) / (-s2_x * s1_y + s1_x * s2_y);
    t = ( s2_x * (yA1 - yA2) - s2_y * (xA1 - xA2)) / (-s2_x * s1_y + s1_x * s2_y);

    if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
    {
        // Collision detected
        //if (i_x != NULL)
        //    *i_x = xA1 + (t * s1_x);
        //if (i_y != NULL)
        //    *i_y = yA1 + (t * s1_y);
        return true;
    }

    return false; // No collision
}

bool CMath::RECT_ON_LINE(int box_left, int box_top, int box_right, int box_bottom, int x1, int y1, int x2, int y2) 
{
//this used to be global, move it out if we use it in more places but here.
	int tmpBox[4];
	tmpBox[0] = box_left;
	tmpBox[1] = box_top;
	tmpBox[2] = box_right;
	tmpBox[3] = box_bottom;
	// check if the line is totally outside the box
	if ((x1 < tmpBox[0] && x2 < tmpBox[0]) ||
		(x1 > tmpBox[2] && x2 > tmpBox[2]) ||
		(y1 < tmpBox[1] && y2 < tmpBox[1]) ||
		(y1 > tmpBox[3] && y2 > tmpBox[3])) {
		return false;
	}
	tmpBox[0] -= x1;
	tmpBox[1] -= y1;
	tmpBox[2] -= x1;
	tmpBox[3] -= y1;
	x2 -= x1;
	y2 -= y1;
	int res1 = ((x2 * -tmpBox[1]) + (y2 * tmpBox[0]));
	int res2 = ((x2 * -tmpBox[3]) + (y2 * tmpBox[0]));
	int res3 = ((x2 * -tmpBox[1]) + (y2 * tmpBox[2]));
	int res4 = ((x2 * -tmpBox[3]) + (y2 * tmpBox[2]));
	if ((res1 < 0 && res2 < 0 && res3 < 0 && res4 < 0) ||
		(res1 > 0 && res2 > 0 && res3 > 0 && res4 > 0)) {
		return false;
	}

	return true;
}

bool CMath::POINT_IN_RECT(int px, int py, int box_left, int box_top, int box_right, int box_bottom)
{
	if (px < box_left)
		return false;
	if (px > box_right)
		return false;
	if (py < box_top)
		return false;
	if (py > box_bottom)
		return false;
	
	return true;
}

int CMath::DISTANCE_LINE_POINT(int x1, int y1, int x2, int y2, int px, int py)
{
	//int v1 = CMath::ANGLE(x3, y3, x1, y1);
	//int v2 = CMath::ANGLE(x3, y3, x2, y2);
	//int angle = CMath::ABSOLUTE_VALUE(v2 - v1);
	double a = CMath::DISTANCE(px, py, x2, y2);
	double b = CMath::DISTANCE(x1, y1, px, py);
	double c = CMath::DISTANCE(x1, y1, x2, y2);
	double p = (a + b + c)/2;

	double area = CMath::SQRT( p*(p-a)*(p-b)*(p-c));

	
	//int area = (x2 - x1)*(y3 - y1) - (y2 - y1)*(x3 - x1);

	//int len_of_line = CMath::DISTANCE(x1, y1, x2, y2);
	//area = CMath::ABSOLUTE_VALUE(area);
	//printf("Area %d    l: %d     res: %d\n", area, c, area*2/c);
	return area*2/c;
}